#ifndef _SECTORMANAGER_
#define _SECTORMANAGER_

#include <iostream>
#include <map>

#include "Message.h"

#include "raknet\Gets.h"
#include "raknet\BitStream.h"
#include "raknet\GetTime.h"
#include "raknet\MessageFilter.h"
#include "raknet\MessageIdentifiers.h"
#include "raknet\RakNetTypes.h"
#include "raknet\StringCompressor.h"
#include "raknet\RakPeerInterface.h"

using namespace std;
using namespace RakNet;

struct Player {
	string id;
	bool ready;
	Player(const string& _id): id(_id), ready(false) {
	}
};

typedef map<RakNetGUID, Player> mapSector;

struct PlayerSector {
	int sectorId;
	string sectorName;

	int playerCount;
	int readyCount;
	bool isPlaying;
	
	RakNetGUID hostGUID;	
	map<RakNetGUID, Player> playerList;

	PlayerSector(const string& _sectorName, const string& ownerId, const RakNetGUID& guid)
		: sectorName(_sectorName), playerCount(0), readyCount(0), isPlaying(false) {
		addPlayer(ownerId, guid);
		hostGUID = guid;
	}

	map<RakNetGUID, Player>& getPlayerList() {
		return playerList;
	}

	void start() {
		if (readyCount < playerCount - 1) {
			return;
		}
		isPlaying = true;
	}

	void addPlayer(const string& playerId, const RakNetGUID& guid) {
		playerList.insert(pair<RakNetGUID, Player>
			(guid, Player(playerId)));
		++playerCount;
	}

	void removePlayer(const RakNetGUID& guid) {
		mapSector::iterator it = playerList.find(guid);
		if (it != playerList.end()) {
			playerList.erase(it);
			--playerCount;	
		}
	}

	bool readyPlayer(const RakNetGUID& guid) {
		mapSector::iterator it = playerList.find(guid);
		if (it != playerList.end()) {
			++readyCount;
			it->second.ready = true;
			return true;
		}
		return false;
	}

	bool cancelPlayer(const RakNetGUID& guid) {
		mapSector::iterator it = playerList.find(guid);
		if (it != playerList.end()) {
			--readyCount;
			it->second.ready = false;
			return true;
		}
		return false;
	}
};

class SectorManager {
public:
	SectorManager();
	~SectorManager();

	void processMessage();
	void sendMessage(Message2*, const SystemAddress&);
	void forwardMessage(Message2*, PlayerSector&, const RakNetGUID& guid);

	// player' s action
	void createSector(Message*, const RakNetGUID&);
	void leaveSector(Message*, const RakNetGUID&);
	int joinSector(Message*, const RakNetGUID&);

	int readySector(Message*, const RakNetGUID&);
	int cancelReadySector(Message*, const RakNetGUID&);

	void packageRoomInfo(Message2&);
	void removeSector(const map<int, PlayerSector>::iterator& it);

	//TODO void connectionKeepCheck();

private:
	map<int, PlayerSector> sectorContainer;
	RakNet::RakPeerInterface* serverNode;
	RakNet::Packet* p;

	BitStream bitStream;

	int roomId;
	int roomCount;
};


#endif